import Dep from './Dep'

var uid = 0

export default class Watcher {
  constructor(target, expression, callback) {
    // target: 数据对象，如obj
    // expression：表达式，如b.c
    // callback：依赖变化时触发的回调
    console.log('我是Watcher类构造器')
    this.id = uid++
    // this指向window
    this.target = target
    // console.log(this)
    this.getter = parsePath(expression)
    this.callback = callback
    //  get方法会读取数据的值，从而触发了数据的getter
    this.value = this.get()
  }
  // 当收到数据变化的消息时执行该方法
  update() {
    this.run()
  }
  // get方法的作用就是获取自己依赖的数据
  get() {
    // 进入依赖收集阶段,将全局的window.target设置为Watcher本身
    // this就是Watcher
    Dep.target = this
    const obj = this.target

    var value

    // 只要能找到,就一直找
    try {
      value = this.getter(obj)
    } finally {
      Dep.target = null
    }
    return value
  }
  run() {
    // 得到并且唤起
    this.getAndInvoke(this.callback)
  }
  getAndInvoke(cb) {
    const value = this.get()
    if (value !== this.value || typeof value == 'object') {
      const oldValue = this.value
      this.value = value
      cb.call(this.target, value, oldValue)
    }
  }
}
function parsePath(str) {
  var segments = str.split('.')
  return obj => {
    for (let i = 0; i < segments.length; i++) {
      if (!obj) return
      obj = obj[segments[i]]
    }
    return obj
  }
}
